
/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

var self = this;
 
if( !self.buRRRn )
    {
    /* Namespace: buRRRn
       This is the folder and namespace
       containing all the libraries and frameworks
       released by buRRRn.
    */
    self.buRRRn = {};
    }

if( !buRRRn.core2 )
    {
    /* Namespace: core2
    */
    buRRRn.core2 = {};
    }

/* Property: version
   Contains core2 version.
*/
buRRRn.core2.version = "1.1.0." + parseInt( "$Rev: 131 $".split( " " )[1] );;
 
/* Property: config
   Contains core2 configuration options.
*/
buRRRn.core2.config = {};

/* Property: CRLF
   define the Carriage Return for the environment.
*/
buRRRn.core2.config.CRLF = "\n";

/* Property: backwardCompatible
   Makes core v1.1.*+ backward compatible with core v1.0.
*/
buRRRn.core2.config.backwardCompatible = false;

/* Property: showInfo
   Allow to show core2 config at frist run.
*/
buRRRn.core2.config.showInfo = false;

/* Property: fixGetYear
   Boolean property to patch or not
   the <Date.prototype.getYear> method.
   
   see:
   JavaScript getYear returns "100" for 2000
   <https://bugzilla.mozilla.org/show_bug.cgi?id=22964>
   
   deprecated:
   _global.$CORE2_FIXGETYEAR
*/
buRRRn.core2.config.fixGetYear = false;

/* Property: errorCtor
   Boolean property to define or override
   the <Error> Object constructor.
   
   deprecated:
   _global.$CORE2_ERROR_CTOR
*/
buRRRn.core2.config.errorCtor = false;

/* Property: allowToSource
   Boolean property to define
   the toSource method in core objects.
   
   note:
   the serialization methods has been
   moved to eden, but for backward compatibility sake
   (or maybe just because you liked it ;))
   you can put back those methods in the prototype.
*/
buRRRn.core2.config.allowToSource = false;

/* Property: opAsTopLevel
   Boolean option to allow to make operators function
   as top level function
   
   ex:
   (code)
   //opAsTopLevel = true;
   if( is(something)(String) )
       {
       trace( "found a string" );
       } 
   (end)
*/
buRRRn.core2.config.opAsTopLevel = false;


/* Property: globalsReserved
   List of global reserved keywords.
*/
buRRRn.core2.config.globalsReserved = [ "_global" ];

/* Property: host
   Contains the host name.
   
   note:
   host can be
   Unknown - host has not been found
   WSH     - Windows Script host
   JSDB    - JavaScript for DataBase
   Browser - Browsers (MSIE, Firefox, Opera, Safari, etc.)
   Flash   - Flash player
*/
buRRRn.core2.config.host = "";

/* Property: hostMoreInfo
   Contains more info (build and/or version etc.)
   about the host environment.
*/
buRRRn.core2.config.hostMoreInfo = "";

/* Property: language
   Contains the ECMAScript language breed.
   
   note:
   language can be
   ECMAScript - by default
   JavaScript - SpiderMonkey or any other engine in the browser
   JScript    - Microsoft engine
*/
buRRRn.core2.config.language = "";

/* Property: languageMoreInfo
   Contains the version of the language if found.
*/
buRRRn.core2.config.languageMoreInfo = "";


/* Property: strings
   Contains core2 resource strings.
*/
buRRRn.core2.strings = {};

buRRRn.core2.strings.hostNotFound = "Host not found";
buRRRn.core2.strings.message = "";

/*Method: getString
  Gets the resource string contained in name
  or the empty string if not found.
*/
buRRRn.core2.getString = function( name/*String*/ )/*String*/
    {
    if( !this.strings[name] )
        {
        return "";
        }
    
    return this.strings[name];
    }

/* Method: isGlobalReserved
   Returns a Boolean that indicates if the
   supplied name keyword is reserved or not.
*/
buRRRn.core2.isGlobalReserved = function( name/*String*/ )/*Boolean*/
    {
    var words = this.config.globalsReserved.join( "|" );
    if( words.indexOf( name ) > -1 )
        {
        return true;
        }
    
    return false;
    }

buRRRn.core2.addReserved = function( name/*String*/ )
    {
    var words = this.config.globalsReserved.join("|");
    
    var contains = function( word/*String*/ )
        {
        return words.indexOf( word ) > -1;
        }
    
    if( !contains( name ) )
        {
        this.config.globalsReserved.push( name );
        }
    }

/* Method: introspectEnvironment
*/
buRRRn.core2.introspectEnvironment = function()
    {
    var env = { host:"", lang:"" };
    
    if( (this.config.host != "") &&
        (this.config.language != "") )
        {
        env.host = this.config.host;
        env.lang = this.config.language;
        return env;
        }

    if( (typeof WSH != "undefined") || (typeof WScript != "undefined") )
        {
        env.host = "WSH";
        env.lang = "JScript";
        this.config.hostMoreInfo     = WScript.Version;
        this.config.languageMoreInfo = ScriptEngineMajorVersion()+"."+ScriptEngineMinorVersion()+"."+ScriptEngineBuildVersion();
        }
    
    if( (typeof Server != "undefined") || (typeof Stream != "undefined") || (typeof ActiveX != "undefined") )
        {
        env.host = "JSDB";
        env.lang = "JavaScript";
        this.config.hostMoreInfo     = "build " + system.buildDate;
        this.config.languageMoreInfo = system.version/100;
        }
    
    if( (typeof $version != "undefined") || (typeof MovieClip != "undefined") )
        {
        env.host = "Flash";
        env.lang = "ActionScript";
        
        this.config.hostMoreInfo = $version;
        }
    
    if( (typeof document != "undefined") || (typeof window != "undefined") ||
        (typeof navigator != "undefined") || (typeof location != "undefined") )
        {
        env.host = "Browser";
        env.lang = "JavaScript";
        
        if( navigator.userAgent.indexOf("MSIE") != -1 )
            {
            this.config.hostMoreInfo = "MSIE";
            env.lang = "JScript";
            this.config.languageMoreInfo = ScriptEngineMajorVersion()+"."+ScriptEngineMinorVersion()+"."+ScriptEngineBuildVersion();
            }
        else if( navigator.userAgent.indexOf("Firefox") != -1 )
            {
            this.config.hostMoreInfo = "Firefox";
            }
        else if( navigator.userAgent.indexOf("Opera") != -1 )
            {
            this.config.hostMoreInfo = "Opera";
            }
        else if( navigator.userAgent.indexOf("AppleWebKit") != -1 )
            {
            this.config.hostMoreInfo = "Safari";
            }
        
        if( location.href.split( "." ).pop() == "hta" )
            {
            this.config.hostMoreInfo = "MSIE HTA";
            }
        
        }
    
    if( (env.host == "") || (env.lang == "") )
        {
        env.host = "Unknown";
        env.lang = "ECMAScript";
        trace( "## WARNING : " + this.strings.hostNotFound + " ##" );
        }
    
    this.config.host     = env.host;
    this.config.language = env.lang;
    return env;
    }

/* Method: getHost
   Returns the host name.
*/
buRRRn.core2.getHost = function()
    {
    if( this.config.host != "" )
        {
        return this.config.host;
        }
    
    var env = this.introspectEnvironment();
    return env.host;
    }

/* Method: getLanguage
   Returns the language breed.
*/
buRRRn.core2.getLanguage = function()
    {
    if( this.config.language != "" )
        {
        return this.config.language;
        }
    
    var env = this.introspectEnvironment();
    return env.lang;
    }

/* Method: hasFunctionSource
   Returns a Boolean to indicate if the host support
   to retrieve the body of a function as string.
   
   deprecated:
   _global.$CORE2_FCTNSTRING
*/
buRRRn.core2.hasFunctionSource = function()
    {
    
    var test = function()
        {
        return "true";
        }
    
    return test.toString().indexOf( "return \"true\";" ) > 0;
    }

/* Method: introspectGlobal
   Scan browser defined globals
   and store them in <globalsReserved>.
   
   note:
   We need to do that to avoid "too much recursion errors"
   inside browsers when we do code introspection.
*/
buRRRn.core2.introspectGlobal = function()
    {
    switch( this.getHost() )
        {
        case "JSDB":
        break;
        
        case "WSH":
        this.addReserved( "WSH" );
        this.addReserved( "WScript" );
        break;
        
        case "Browser":
        this.addReserved( "document" );
        this.addReserved( "window" );
        this.addReserved( "navigator" );
        this.addReserved( "location" );
        
        for( var o in self )
            {
            
            if( (o == "buRRRn") || (o == "core2") || (o == "_global") )
                {
                continue;
                }
            
            this.addReserved( o );
            }
        
        break;
        }
    }

/* Method: infos
   Traces core2 informations.
*/
buRRRn.core2.infos = function()
    {
    var hostmi = "";
    var langmi = "";
    
    if( this.config.hostMoreInfo != "" )
        {
        hostmi = " ( " + this.config.hostMoreInfo + " )";
        }
    
    if( this.config.languageMoreInfo != "" )
        {
        langmi = " v" + this.config.languageMoreInfo;
        }
    
    trace( "core2 v"+this.version );
    trace( "-- Environment --" );
    trace( "hasFunctionSource:  " + this.hasFunctionSource() );
    trace( "host:               " + this.getHost() + hostmi );
    trace( "language:           " + this.getLanguage() + langmi );
    
    trace( "-- Configuration options --" );
    trace( "backwardCompatible: " + this.config.backwardCompatible );
    trace( "showInfo:           " + this.config.showInfo );
    trace( "fixGetYear:         " + this.config.fixGetYear );
    trace( "errorCtor:          " + this.config.errorCtor );
    trace( "allowToSource:      " + this.config.allowToSource );
    trace( "opAsTopLevel:       " + this.config.opAsTopLevel );
    
    trace( "globalsReserved:   [" + this.config.globalsReserved + "]" );
    
    }

/* Method: setTrace
   Override the trace function.
*/
buRRRn.core2.setTrace = function( traceFunction/*Function*/ )
    {
    _global.trace = function( o )
        {
        traceFunction( o );
        }
    
    //flush message
    if( this.strings.message != "" )
        {
        trace( this.strings.message );
        this.strings.message = "";
        }
    }

/* Method: main
   Execute the core2 main entry point.
   
   note:
   general object namespace structure
   
   (code)
   {namespace}
          |_ config
          |      |_ option1
          |      |_ option2
          |      |_ etc.
          |      |_ strings
          |            |_ resource_string1
          |            |_ resource_string2
          |            |_ etc.
          |_ utilityMethod1
          |_ utilityMethod2
          |_ etc.
          |_ main
   (end)
   
   *core2.config*
   store configuration options
   
   ex:
   (code)
   //before
   if( $CORE2_FIXGETYEAR )
       {
       //...
       }
   
   //after
   if( core2.config.fixGetYear )
       {
       //...
       }
   (end)
   
   *core2.config.strings*
   store resource strings
   
   ex:
   (code)
   if( this.getHost() == "Unknown" )
       {
       trace( this.getString( "hostNotFound" ) );
       }
   (end)
   
*/
buRRRn.core2.main = function()
    {
    this.introspectEnvironment();
    this.introspectGlobal();
    
    switch( this.getHost() )
        {
        case "WSH":
        self._global = self;
        delete self;
        this.config.errorCtor = false;
        this.config.CRLF = "\n";
        
        _global.trace = function( o )
            {
            WScript.Echo( String( o ) );
            }
        
        break;
        
        case "JSDB":
        self._global = self;
        delete self;
        this.config.errorCtor = false;
        this.config.CRLF = "\n";
        
        _global.trace = function( o  )
            {
            writeln( String( o ) );
            }
        
        break;
        
        case "Flash":
        _global.buRRRn = self.buRRRn;
        delete self;
        this.config.errorCtor = true;
        this.config.CRLF = "\n";
        
        Object.prototype.propertyIsEnumerable = Object.prototype.isPropertyEnumerable;
        //use ASPF
        break;
        
        case "Browser":
        self._global = self;
        delete self;
        this.config.errorCtor = false;
        this.config.CRLF = "\r\n";
        
        if( this.config.hostMoreInfo == "Firefox" )
            {
            this.config.CRLF = "\n";
            }
        
        _global.trace = function( o )
            {
            buRRRn.core2.strings.message += String( o + buRRRn.core2.config.CRLF );
            }
        
        break;
        
        case "Unknown":
        default:
        }
    
    }

buRRRn.core2._changeCompatibility = function()
    {
    
    if( this.config.backwardCompatible )
        {
        _global.GetTypeOf = buRRRn.Reflection.getTypeOf;
        _global.GetObjectPath = function( o )
            {
            return buRRRn.Reflection.getObjectPath( o );
            }
        }
    else
        {
        if( _global.GetTypeOf )
            {
            delete _global.GetTypeOf;
            }
        
        if( _global.GetObjectPath )
            {
            delete _global.GetObjectPath;
            }
        }
    
    }

buRRRn.core2._changeToSource = function()
    {
    
    if( this.config.backwardCompatible && this.config.allowToSource )
        {
        Boolean.prototype.toSource = function()
            {
            return (this == true) ? "true": "false";
            }
        
        Number.prototype.toSource = function()
            {
            return this.toString();
            }
        
        Function.prototype.toSource = function()
            {
            return "(function)";
            }
                
        String.prototype.toSource = function()
            {
            return buRRRn.eden.Serializer.emitString( this );
            }        
        
        Object.prototype.toSource = function()
            {
            return buRRRn.eden.Serializer.emitObject( this );
            }
        
        Array.prototype.toSource = function()
            {
            return buRRRn.eden.Serializer.emitArray( this );
            }
        
        Date.prototype.toSource = function()
            {
            return buRRRn.eden.Serializer.emitDate( this );
            }
        
        Error.prototype.toSource = function()
            {
            return "new Error(\""+this.message+"\")";
            }
        
        _global.ToSource = function()
            {
            return buRRRn.eden.Serializer.emitGlobal( _global );
            }
        
        }
    else
        {
        if( Boolean.prototype.toSource )
            {
            delete Boolean.prototype.toSource;
            }
        
        if( Number.prototype.toSource )
            {
            delete Number.prototype.toSource;
            }
        
        if( Function.prototype.toSource )
            {
            delete Function.prototype.toSource;
            }
        
        if( String.prototype.toSource )
            {
            delete String.prototype.toSource;
            }
        
        if( Object.prototype.toSource )
            {
            delete Object.prototype.toSource;
            }
        
        if( Array.prototype.toSource )
            {
            delete Array.prototype.toSource;
            }
        
        if( Date.prototype.toSource )
            {
            delete Date.prototype.toSource;
            }
        
        if( Error.prototype.toSource )
            {
            delete Error.prototype.toSource;
            }
        
        if( _global.ToSource )
            {
            delete _global.ToSource;
            }
        
        }
    
    }

buRRRn.core2._changeOperators = function()
    {
    if( this.config.opAsTopLevel )
        {
        _global.is = function( o )
            {
            return buRRRn.core2.operators.is( o );
            }
        }
    else
        {
        if( _global.is )
            {
            delete _global.is;
            }
        
        }
    }

/* Method: after
   Execute after the main function,
   for cases where you can not or don't want to execute
   within the main function.
*/
buRRRn.core2.after = function()
    {
    
    //operators
    this._changeOperators();
    
    //compatibility
    this._changeCompatibility();
    
    //toSource
    this._changeToSource();
    
    if( this.config.showInfo )
        {
        this.infos();
        }
    }

/* Method: changeConfig
   Allows to dynamically change the core2 configuration.
   
   usage:
   (code)
   buRRRn.core2.changeConfig( {backwardCompatible:true,allowToSource:true} );
   //core v1.0 code here
   buRRRn.core2.changeConfig( {backwardCompatible:false,allowToSource:false} );
   //core2 v1.1 code here, no more function in _global, etc.
   (end)
*/
buRRRn.core2.changeConfig = function( options/*Object*/ )
    {
    
    if( options.backwardCompatible && (options.backwardCompatible != this.config.backwardCompatible) )
        {
        this.config.backwardCompatible = options.backwardCompatible;
        this._changeCompatibility();
        
        if( options.allowToSource && (options.allowToSource != this.config.allowToSource) )
            {
            this.config.allowToSource = options.allowToSource;
            this._changeToSource();
            }
        
        }
    
    }

/* note:
   ActionScript does not support the construct
   core.main = function()
       {
       //...
       }(); //autoexecute
   so for compatibility sake we don't use that construct
   
   Also some ECMAScript implementation can not use
   the 'this' keyword inside such auto-executed function.
*/
buRRRn.core2.main(); //autoexecute

/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: Array
   Provides support for creation of arrays of any data type.
   
   attention:
   Array in ECMAScript does not have a fixed size,
   so we can dynamically add or remove elements.
   
   We deal only with 1-dimension array, if we feel the need
   we could add another constructor to deal with more than 1 dimension latter.
*/

/* Method: clone
   Creates a shallow copy of the Array.
   
   note:
   A shallow copy of an Array copies only the elements of the Array,
   whether they are reference types or value types,
   but it does not copy the objects that the references refer to.
   
   The references in the new Array point to the same objects that
   the references in the original Array point to.

   In contrast, a deep copy of an Array copies the elements and
   everything directly or indirectly referenced by the elements.
   
   attention:
   when applying this behaviour to ECMAscript a shallow copy
   will only copy primitive types and pointers to reference types.
   
   example:
   (code)
   toto = [1,{a:0,b:1},[2,3],"hello",true];
   titi = toto.clone();
   (end)
   
   memory dump:
   (code)
   toto = [object #1, class 'Array']
        [
        0:1,
        1:[object #2, class 'Object'] {
          b:1,
          a:0
        },
        2:[object #3, class 'Array'] [
          0:2,
          1:3
        ],
        3:"hello",
        4:true
        ]

   titi = [object #4, class 'Array']
        [
        0:1,
        1:[object #2, class 'Object'],
        2:[object #3, class 'Array'],
        3:"hello",
        4:true
        ]
   (end)
*/
/*!## TODO: make a schema for the memory representation */
Array.prototype.clone = function()
    {
    return this.concat();
    }

/* Method: concat
   Returns a new Array consisting of a combination of two or more arrays (*ECMA-262*).
   
   (code)
   Array.prototype.concat = function( ... )
       {
       [native code]
       }
   (end)
*/

/* Method: contains
   Returns whether the Array contains a particular item.
*/
Array.prototype.contains = function( value )
    {
    return( this.indexOf( value ) > -1 );
    }

/* Method: copy
   Creates a deep copy of the Array.
*/
Array.prototype.copy = function()
    {
    var arr, i;
    arr = [];
    
    for( i=0; i<this.length; i++ )
        {
        if( this[i] === undefined )
            {
            arr[i] = undefined;
            continue;
            }
        
        if( this[i] === null )
            {
            arr[i] = null;
            continue;
            }
        
        arr[i] = this[i].copy();
        }
    
    return arr;
    }

/* Method: copyTo
   Copies by value all the elements of the current one-dimensional Array
   to the specified one-dimensional Array.
   
   Parameters:
      destination - an array where to copy
      index       - optionnal, allow you to specify at which index
                    you want to start to copy the elements
*/
Array.prototype.copyTo = function( /*Array*/ destination, /*int*/ index )
    {
    var i;
    
    if( destination == null )
        {
        return; /* ArgumentNullException */
        }
    
    if( index == null )
        {
        index = 0;
        }
    
    for( i=0; i<this.length; i++, index++ )
        {
        if( this[i] === undefined )
            {
            destination[index] = undefined;
            continue;
            }
        
        if( this[i] === null )
            {
            destination[index] = null;
            continue;
            }
        
        destination[index] = this[i].copy();
        }
    }

/* Method: equals
   compare if two Arrays are equal by value.
*/
Array.prototype.equals = function( arrObj )
    {
    var i;
    
    if( (arrObj == null) || (buRRRn.Reflection.getTypeOf( arrObj ) != "array") )
        {
        return false;
        }
    
    if( this == arrObj )
        {
        return true;
        }
    
    if( this.length != arrObj.length )
        {
        return false;
        }
    
    for( i=0; i<this.length; i++ )
        {
        if( this[i] == null )
            {
            if( this[i] != arrObj[i] )
                {
                return false;
                }
            continue;
            }
        
        if( !this[i].equals( arrObj[i] ) )
            {
            return false;
            }
        }
    
    return true;
    }

if( !Array.prototype.every )
    {
    
    /* Method: every
       Tests whether all elements in the array pass the test
       implemented by the provided function.
       
       note:
       callback is invoked with three arguments:
       - the value of the element
       - the index of the element
       - the Array object being traversed
       
       example:
       (code)
       myCallback( value, index, arrObj )
           {
           //[...]
           }
       (end)
       
    */
    Array.prototype.every = function( /*Function*/ callback, thisObject )
        {
        var len, i;
        len = this.length;
        
        if( thisObject == null )
            {
            thisObject = _global;
            }
        
        for( i=0; i<len; i++ )
            {
            if( !callback.call( thisObject, this[i], i, this ) )
                {
                return false;
                }
            }
        
        return true;
        }

    }

if( !Array.prototype.filter )
    {
    
    /* Method: filter
       Creates a new array with all of the elements of the current
       array for which the provided filtering function returns true.
       
       note:
       callback is invoked with three arguments:
       - the value of the element
       - the index of the element
       - the Array object being traversed
       
       example:
       (code)
       myCallback( value, index, arrObj )
           {
           //[...]
           }
       (end)
    */
    Array.prototype.filter = function( /*Function*/ callback, thisObject )
        {
        var arr, i;
        arr = [];
        
        if( thisObject == null )
            {
            thisObject = _global;
            }
        
        for( i=0; i<this.length; i++ )
            {
            if( callback.call( thisObject, this[i], i, this ) )
                {
                if( this[i] === undefined )
                    {
                    arr.push( undefined );
                    continue;
                    }
                
                if( this[i] === null )
                    {
                    arr.push( null );
                    continue;
                    }
                            
                arr.push( this[i].copy() );
                }
            }
        
        return arr;
        }
    
    }

if( !Array.prototype.forEach )
    {
    
    /* Method: forEach
       Calls a function for each element in the array.
       
       note:
       callback is invoked with three arguments:
       - the value of the element
       - the index of the element
       - the Array object being traversed
       
       example:
       (code)
       myCallback( value, index, arrObj )
           {
           //[...]
           }
       (end)
    */
    Array.prototype.forEach = function( /*Function*/ callback, thisObject )
        {
        var len, i;
        len = this.length;
        
        if( thisObject == null )
            {
            thisObject = _global;
            }
        
        for( i=0; i<len; i++ )
            {
            callback.call( thisObject, this[i], i, this );
            }
        }
    
    }

/* StaticMethod: fromArguments
   Returns an Array object from a function Arguments object.
*/
Array.fromArguments = function( args )
    {
    var arr, i;
    
    arr = [];
    
    for( i=0; i<args.length; i++ )
        {
        arr.push( args[i] );
        }
    
    return arr;
    }

/* Method: indexOf
   Returns the index of the first occurrence of a value
   in a one-dimensional Array or in a portion of the Array.
   
   Parameters:
   startIndex - optionnal, allows to specify the starting index of the search
   count      - allows to limit the number of elements to search in the array
*/
Array.prototype.indexOf = function( value, /*int*/ startIndex, /*int*/ count )
    {
    var i;
    
    /*!## TODO: replace this.length by the length var
          var length = this.length;
    */
    
    if( startIndex == null )
        {
        startIndex = 0;
        }
    
    if( count == null  )
        {
        count = this.length - startIndex;
        }
    
    if( (startIndex < 0) || (startIndex > this.length) )
        {
        return; //ArgumentOutOfRangeException
        }
    
    if( (count < 0) || (count > (this.length - startIndex)) )
        {
        return; //ArgumentOutOfRangeException
        }
    
    /* attention:
       the null data type can't have
       properties or methods so if an index
       of the array is the null data type
       this[0] = null;
       and the argument "value" to find is also null
       doing
       null.equals( null );
       will generate an error.
       
       to correct that we transform the argument "value"
       into an object which resolve to null data type,
       a sort of nullable object, yes it's a hack ;).
    */
    if( value == null )
        {
        value = new NullObject();
        }
    
    for( i=0 ; startIndex<this.length; startIndex++, i++ )
        {
        if( value.equals( this[startIndex] ) )
            {
            return startIndex;
            }
        
        if( i == count )
            {
            break;
            }
        }
    
    return -1;
    }

/* StaticMethod: initialize
   Initializes a new Array with an arbitrary number of elements (index),
   with every element containing the passed parameter value or
   by default the null value.
   
   example:
   (code)
   test  = Array.initialize( 3 ); //define [null,null,null]
   test1 = Array.initialize( 3, 0 ); //define [0,0,0]
   test2 = Array.initialize( 3, true ); //define [true,true,true]
   test3 = Array.initialize( 3, "" ); //define ["","",""]
   (end)
*/
Array.initialize = function( /*int*/ index, value )
    {
    if( index == null )
        {
        index = 0;
        }
    
    if( value === undefined )
        {
        value = null;
        }
    
    var arr, i;
    arr = [];
    
    for( i=0; i<index; i++ )
        {
        arr.push( value );
        }
    
    return arr;
    }

/* Method: join
   Returns a string value consisting of all the elements of
   an array concatenated together and separated by the
   specified separator character (*ECMA-262*).
   
   (code)
   Array.prototype.join = function( separator )
       {
       [native code]
       }
   (end)
*/

/* Property: length
   returns an integer value one higher than the
   highest element defined in the array (*ECMA-262*).
*/

if( !Array.prototype.map )
    {
    
    /* Method: map
       Creates a new array with the results of calling a provided
       function on every element in this array.
       
       note:
       callback is invoked with three arguments:
       - the value of the element
       - the index of the element
       - the Array object being traversed
       
       example:
       (code)
       myCallback( value, index, arrObj )
           {
           //[...]
           }
       (end)
    */
    Array.prototype.map = function( /*Function*/ callback, thisObject )
        {
        var arr, i;
        arr = [];
        
        if( thisObject == null )
            {
            thisObject = _global;
            }
        
        for( i=0; i<this.length; i++ )
            {
            arr.push( callback.call( thisObject, this[i], i, this ) );
            }
        
        return arr;
        }
    
    }

/* Method: pop
   Removes the last element from an array and returns it (*ECMA-262*).
   
   (code)
   Array.prototype.pop = function()
       {
       [native code]
       }
   (end)
*/

/* Method: push
   Appends new elements to an array, and returns the new length of the array (*ECMA-262*).
   
   (code)
   Array.prototype.push = function( item1, item2, itemN )
       {
       [native code]
       }
   (end)
*/

/* Method: reverse
   Returns an Array object with the elements reversed (*ECMA-262*).
   
   note:
   The reverse method reverses the elements of an Array object in place.
   It does not create a new Array object during execution.
   
   If the array is not contiguous, the reverse method creates elements
   in the array that fill the gaps in the array.
   
   Each of these created elements has the value undefined.
   
   (code)
   Array.prototype.reverse = function()
       {
       [native code]
       }
   (end)
*/

/* Method: shift
   Removes the first element from an array and returns it (*ECMA-262*).
   
   (code)
   Array.prototype.shift = function()
       {
       [native code]
       }
   (end)
*/

/* Method: slice
   Returns a section of an array.
   
   note:
   The slice method returns an Array object containing the
   specified portion of arrayObj.
   
   The slice method copies up to, but not including,
   the element indicated by end.
   
   If start is negative, it is treated as length + start where
   length is the length of the array.
   
   If end is negative, it is treated as length + end where
   length is the length of the array.
   
   If end is omitted, extraction continues to the end of arrayObj.
   
   If end occurs before start, no elements are copied to the new array.
   
   (code)
   Array.prototype.slice = function( /Int/ start, /Int/ end )
       {
       [native code]
       }
   (end)
*/

if( !Array.prototype.some )
    {
    
    /* Method: some
       Creates a new array with the results of calling a provided
       function on every element in this array.
       
       note:
       callback is invoked with three arguments:
       - the value of the element
       - the index of the element
       - the Array object being traversed
       
       example:
       (code)
       myCallback( value, index, arrObj )
           {
           //[...]
           }
       (end)
    */
    Array.prototype.some = function( /*Function*/ callback, thisObject )
        {
        var len, i;
        len = this.length;
        
        if( thisObject == null )
            {
            thisObject = _global;
            }
        
        for( i=0; i<len; i++ )
            {
            if( callback.call( thisObject, this[i], i, this ) )
                {
                return true;
                }
            }
        
        return false;
        }
    
    }

/* Method: sort
   Returns an Array object with the elements sorted (*ECMA-262*).
   
   note:
   The sort method sorts the Array object in place;
   no new Array object is created during execution.
   
   If you supply a function in the sortFunction argument,
   it must return one of the following values
   
   - A negative value if the first argument passed is less than the second argument.
   - Zero if the two arguments are equivalent.
   - A positive value if the first argument is greater than the second argument.
   
   (code)
   Array.prototype.sort = function( sortFunction )
       {
       [native code]
       }
   (end)
*/

/* Method: splice
   Removes elements from an array and, if necessary,
   inserts new elements in their place, returning the deleted elements (*ECMA-262*).
   
   note:
   The splice method modifies arrayObj by removing the specified number
   of elements from position start and inserting new elements.
   
   The deleted elements are returned as a new array object.
   
   (code)
   Array.prototype.splice = function( start, deleteCount, ... )
       {
       [native code]
       }
   (end)
*/

/* Method: toSource
   Returns a string representing the source code of the array.
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   (code)
   Array.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: unshift
   Returns an array with specified elements inserted at the beginning (*ECMA-262*).
   
   note:
   The unshift method inserts elements into the start of an array,
   so they appear in the same order in which they appear in the argument list.
   
   (code)
   Array.prototype.unshift = function( item1, item2, itemN )
       {
       [native code]
       }
   (end)
*/

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   Array.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: Boolean
   Creates a new Boolean value.
*/

/* Method: compareTo
   Compares this instance to a specified object and
   returns an indication of their relative values.
*/
Boolean.prototype.compareTo = function( obj )
    {
    if( obj == null )
        {
        return 1;
        }
    
    if( buRRRn.Reflection.getTypeOf( obj ) != "boolean" )
        {
        return; //ArgumentException - arg must be boolean
        }
    
    if( this.equals( obj )  )
        {
        return 0;
        }
    else if( this.equals( false ) )
        {
        return -1;
        }
    
    return 1;
    }

/* Method: clone
   Returns a copy by reference of this boolean.
   
   attention:
   If the instance is a primitive the behaviour
   is to return a copy by value.
*/
Boolean.prototype.clone = function()
    {
    return this;
    }

/* Method: copy
   Returns a copy by value of this object.
   
   note:
   this method always return a primitive.
*/
Boolean.prototype.copy = function()
    {
    return this.valueOf();
    }

/* Method: equals
   compare if two Booleans are equal by value.
*/
Boolean.prototype.equals = function( boolObj )
    {
    if( (boolObj == null) || (buRRRn.Reflection.getTypeOf( boolObj ) != "boolean") )
        {
        return false;
        }
    
    return( this.valueOf() == boolObj.valueOf() );
    }

/* Method: toSource
   Returns a string representing the source code of the boolean.
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   (code)
   Boolean.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   Boolean.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: Date
   Enables basic storage and retrieval of dates and times.
*/

/* Method: clone
   Returns a copy by reference of this object.
*/
Date.prototype.clone = function()
    {
    return this;
    }

/* Method: copy
   Creates a new instance of Date with the same value of the current object.
*/
Date.prototype.copy = function()
    {
    return new Date( this.valueOf() );
    }

/* Method: equals
   compare if two Dates are equal by value.
   
   note:
   as the exact same date are never equal by value,
   we compare the eguality of the string representation of the dates.
*/
Date.prototype.equals = function( datObj )
    {
    if( (datObj == null) || (buRRRn.Reflection.getTypeOf( datObj ) != "date") )
        {
        return false;
        }
    
    return( this.toString() == datObj.toString() );
    }

/* Getter: getDate
   Returns the day of the month for the specified date
   according to local time (*ECMA-262*).
   
   note:
   The return value is an integer between 1 and 31
   that represents the date value in the Date object.
   
   (code)
   Date.prototype.getDate = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setDate
   Sets the day of the month for a specified date
   according to local time (*ECMA-262*).
   
   attention:
   If the value of the argument dayValue is greater than
   the number of days in the month stored in the Date object
   or is a negative number, the date is set to a date equal
   to numDate minus the number of days in the stored month.
   
   For example, if the stored date is January 5, 1996,
   and setDate(32) is called, the date changes to February 1, 1996.
   Negative numbers have a similar behavior.

   
   (code)
   Date.prototype.setDate = function( dayValue )
    {
    [native code]
    }
   (end)
*/

/* Method: getDay
   Returns the day of the week for the specified date
   according to local time (*ECMA-262*).
   
   note:
   The value returned from the getDay method is an integer between 0 and 6
   representing the day of the week and corresponds to a day of the week as follows
   
   0 - Sunday 
   1 - Monday 
   2 - Tuesday 
   3 - Wednesday 
   4 - Thursday 
   5 - Friday 
   6 - Saturday 

   
   (code)
   Date.prototype.getDay = function()
    {
    [native code]
    }
   (end)
*/

if( buRRRn.core2.config.fixGetYear )
    {
    /* Getter: getYear
       Returns the year of the specified date
       according to local time (*ECMA-262*).
       
       attention:
       consider this method deprecated, use getFullYear instead.
       
       - JScript v1.0
         setYear uses a value that is the result of the addition
         of 1900 to the year value provided by numYear, regardless
         of the value of the year.
         For example, to set the year to 1899 numYear is -1 and to
         set the year 2000 numYear is 100.
       
       - JavaScript 1.0 to 1.2
         https://bugzilla.mozilla.org/show_bug.cgi?id=22964
         Returns the year in the specified date according to local time.
         JavaScript 1.3: deprecated; also, getYear returns the year minus
         1900 regardless of the year specified
       
       (code)
       Date.prototype.getFullYear = function()
        {
        [native code]
        }
       (end)
    */
    /*!## FIXME: Not Tested */
    Date.prototype.getYear = Date.prototype.getFullYear;
    }

/* Setter: setYear
   Sets the year value in the Date object (*ECMA-262*).
   
   attention:
   consider this method deprecated, use setFullYear instead.
      
   (code)
   Date.prototype.setYear = function( year )
    {
    [native code]
    }
   (end)
*/
/*!## TODO: Should we provide a fix for setYear also or not ? */

/* Getter: getFullYear
   Returns the year of the specified date
   according to local time (*ECMA-262*).
   
   note:
   The getFullYear method returns the year as an absolute number.
   
   For example, the year 1976 is returned as 1976.
   
   This avoids the year 2000 problem where dates beginning with
   January 1, 2000 are confused with those beginning with January 1, 1900.
   
   (code)
   Date.prototype.getFullYear = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setFullYear
   Sets the full year for a specified date
   according to local time (*ECMA-262*).
   
   note:
   only the year argument is required, the others are optional.
   
   (code)
   Date.prototype.setFullYear = function( year, month, date )
    {
    [native code]
    }
   (end)
*/

/* Getter: getHours
   Returns the hour in the specified date
   according to local time (*ECMA-262*).
   
   note:
   The getHours method returns an integer between 0 and 23,
   indicating the number of hours since midnight.
   
   (code)
   Date.prototype.getHours = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setHours
   Sets the hours for a specified date
   according to local time (*ECMA-262*).
   
   note:
   only the hour argument is required, the others are optional.
   
   (code)
   Date.prototype.setHours = function( hour, min, sec, ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getMilliseconds
   Returns the milliseconds in the specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.getMilliseconds = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setMilliseconds
   Sets the milliseconds for a specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.setMilliseconds = function( ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getMinutes
   Returns the minutes in the specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.getMinutes = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setMinutes
   Sets the minutes for a specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.setMinutes = function( min, sec, ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getMonth
   Returns the month in the specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.getMonth = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setMonth
   Sets the month for a specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.setMonth = function( month, date )
    {
    [native code]
    }
   (end)
*/

/* Getter: getSeconds
   Returns the seconds in the specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.getSeconds = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setSeconds
   Sets the seconds for a specified date
   according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.setSeconds = function( sec, ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getTime
   Returns the numeric value corresponding to the time
   for the specified date according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.getTime = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setTime
   Sets the value of a Date object according to local time (*ECMA-262*).
   
   (code)
   Date.prototype.setTime = function( ms )
    {
    [native code]
    }
   (end)
*/

/* Method: getTimezoneOffset
   Returns the difference in minutes between the local time
   on the host computer and Universal Coordinated Time (UTC) (*ECMA-262*).
   
   (code)
   Date.prototype.getTimezoneOffset = function()
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCDate
   Returns the day (date) of the month in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCDate = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCDate
   Sets the day of the month for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCDate = function( date )
    {
    [native code]
    }
   (end)
*/

/* Method: getUTCDay
   Returns the day of the week in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCDay = function()
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCFullYear
   Returns the year in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCFullYear = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCFullYear
   Sets the full year for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCFullYear = function( year, month, date )
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCHours
   Returns the year in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCHours = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCHours
   Sets the hour for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCHours = function( hour, min, sec, ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCMilliseconds
   Returns the milliseconds in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCMilliseconds = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCMilliseconds
   Sets the milliseconds for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCMilliseconds = function( ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCMinutes
   Returns the minutes in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCMinutes = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCMinutes
   Sets the minutes for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCMinutes = function( min, sec, ms )
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCMonth
   Returns the month according in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCMonth = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCMonth
   Sets the month for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCMonth = function( month, date )
    {
    [native code]
    }
   (end)
*/

/* Getter: getUTCSeconds
   Returns the seconds in the specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.getUTCSeconds = function()
    {
    [native code]
    }
   (end)
*/

/* Setter: setUTCSeconds
   Sets the seconds for a specified date
   according to universal time (*ECMA-262*).
   
   (code)
   Date.prototype.setUTCSeconds = function( sec, ms )
    {
    [native code]
    }
   (end)
*/

/* StaticMethod: parse
   Returns the number of milliseconds in a date string
   since January 1, 1970, 00:00:00, local time (*ECMA-262*).
   
   note:
   the str argument is a string argument containing
   the date in a format such as "Mar 21, 2005 16:21:00".
   
   (code)
   Date.parse = function( str )
       {
       [native code]
       }
   (end)
*/

/* Method: toGMTString
   Converts a date to a string, using the Internet GMT conventions (*ECMA-262*).
   
   Date.prototype.toGMTString = function()
       {
       [native code]
       }
*/

/* Method: toSource
   Returns a string representing the source code of the object.
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   (code)
   Date.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: toUTCString
   Converts a date to a string, using the universal time convention (*ECMA-262*).
   
   Date.prototype.toUTCString = function()
       {
       [native code]
       }
*/

/* StaticMethod: UTC
   Returns the number of milliseconds in a Date object
   since January 1, 1970, 00:00:00, universal time (*ECMA-262*).
   
   note:
   only the arguments year, month, day are required,
   the others are optional.
   
   (code)
   Date.UTC = function( year, month, day, hour, min, sec, ms )
       {
       [native code]
       }
*/

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   Date.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

if( buRRRn.core2.config.errorCtor )
    {
    /* Constructor: Error
       Contains information about errors.
       
       note:
       We provide an Error object constructor
       for hosts not providing one (Flash 6 for exemple).
    */
    _global.Error = function( /*String*/ message )
        {
        if( message == null )
            {
            message = "";
            }
        
        /*!## TODO: this property should be defined in prototype, check that */
        this.name    = "Error";
        this.message = String( message );
        }
    }

/* SharedProperty: message
   The default initial value of the error message.
   
   attention:
   see ECMA-262 spec 15.11.4.3 Error.prototype.message.
   
   "The initial value of Error.prototype.message is an implementation-defined string."
   
   In FLash ActionScript message default value is "Error".
   
   In Opera browser message default value is "Generic Error".
   
   Because we want the same message for all hosts we then override this default value.
*/
Error.prototype.message = "";

/* Method: equals
   compare if two Errors are equal by value.
*/
Error.prototype.equals = function( errObj )
    {
    if( (errObj == null) || (buRRRn.Reflection.getTypeOf( errObj ) != "error") )
        {
        return false;
        }
    
    return( this.toString() == errObj.toString() );
    }

/* Getter: getMessage
   Returns the error message string.
*/
Error.prototype.getMessage = function()
    {
    if( this.message == undefined )
        {
        return "";
        }
    
    return this.message;
    }

/* Property: message
   Returns an error message string (*ECMA-262*).
*/

/* SharedProperty: name
   Returns the name of an error (*ECMA-262*).
   
   Default value is "Error".
   
   (code)
   Error.prototype.name = [native code];
   //Error.prototype.name = "Error";
   (end)
*/

/* Method: toSource
   Returns a string representing the source code of the object.
*/


/* Method: toString
   Converts the value of this instance to its
   equivalent string representation.
*/
Error.prototype.toString = function()
    {
    var separator, message;
    separator = " : ";
    message   = this.getMessage();
    
    if( message != "" )
        {
        message = separator + message;
        }
    
    return "## " + this.name + message + " ##";
    }


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: Function
   Creates a new function.
   
   note:
   In ActionScript you can not use the Function constructor,
   but you still can add methods to its prototype.
*/

/* Method: apply
   Allows you to apply a method of another object in the
   context of a different object (the calling object) (*ECMA-262*).
   
   Parameters:
   thisArg  - optionnal, allows to define the object to be used as the current object
   argArray - allows to pass an Array of arguments to the function
   
   (code)
   Function.prototype.apply = function( thisArg, argArray )
       {
       [native code]
       }
   (end)
*/

/* LocalVariable: arguments
   Returns the arguments object for the currently
   executing Function object (*ECMA-262*).
   
   note:
   The arguments property is only defined for a
   function while that function is executing.
   
   (code)
   arguments = [native code];
   (end)
*/

/* Method: call
   Allows you to call (execute) a method of another object
   in the context of a different object (the calling object) (*ECMA-262*).
   
   Parameters:
   thisObj - allows to define the object to be used as the current object,
             if not provided the Global object is used
   ...     - list of arguments to be passed to the function
   
   (code)
   Function.prototype.call = function( thisArg, ... )
       {
       [native code]
       }
   (end)
*/

/* Property: caller
   Returns a reference to the function that invoked the current function (*ECMA-262*).
   
   example:
   (code)
   
   function foobar()
       {
       if( foobar.caller == null )
           {
           return "foobar called from top level";
           }
       else
           {
           return "foobar called by another function";
           }
       }
   
   (end)
*/


/* Method: clone
   Returns a copy by value of this function.
   
   note:
   this method only exists to not break polymorphic calls
   on objects of different types.
   
   attention:
   we can not copy by reference a function,
   if you want to do that use apply or call method to make a kind of delegate.
   
   example:
   (code)
   toto = function( x, y )
       {
       return x + y;
       }
   
   titi = function( x, y )
       {
       return toto.apply( this, arguments );
       }
   (end)
*/
Function.prototype.clone = function()
    {
    return this;
    }

/* Method: copy
   Returns a copy by value of this object.
   
   note:
   the function value is treated as
   a primitive even if it's a type object.
*/
Function.prototype.copy = function()
    {
    return this.valueOf();
    }

/* Method: equals
   compare if two Functions are equal by reference.
*/
Function.prototype.equals = function( fctObj )
    {
    if( (fctObj == null) || (buRRRn.Reflection.getTypeOf( fctObj ) != "function") )
        {
        return false;
        }
    
    if( this.valueOf() == fctObj.valueOf() )
        {
        return true;
        }
    
    /* note:
       In some environments the host return the
       body of the function so we can use that
       to make the comparison.
    */
    if( buRRRn.core2.hasFunctionSource() )
        {
        if( this.toString() == fctObj.toString() )
            {
            return true;
            }
        }
    
    return false;
    }

/* Method: toSource
   Should returns a string representing the source
   code of the function, but instead the choice
   has been made to only return the string
   "(function)".
   
   note:
   This choice is motivated by the fact that even
   if a function is a type it's not a data structure
   but more a code block and with the ISerializable
   interface we are interested only in serialization
   of data structures.
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   attention:
   ActionScript return the string "[type Function]".
   
   (code)
   Function.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   Function.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: NullObject
   Utilitarian object allowing to treat
   a null value as an object.
   
   note:
   usefull for some polymorphic situation.
   
   see: <http://c2.com/cgi/wiki?NullObject>
*/
_global.NullObject = function()
	{
	
	}

/* Method: toString
   Returns a string representing the specified object.
*/
NullObject.prototype.toString = function()
	{
	return "null";
	}

/* Method: valueOf
   Returns the primitive value of the specified object.
*/
NullObject.prototype.valueOf = function()
	{
	return null;
	}


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: Number
   An object representation of the number data type
   and placeholder for numeric constants.
*/

/* Method: clone
   Returns a copy by reference of this boolean.
   
   attention:
   If the instance is a primitive the behaviour
   is to return a copy by value.
*/
Number.prototype.clone = function()
    {
    return this;
    }

/* Method: copy
   Returns a copy by value of this object.
   
   note:
   this method always return a primitive.
*/
Number.prototype.copy = function()
    {
    return this.valueOf();
    }

/* Method: equals
   compare if two Numbers are equal by value
*/
Number.prototype.equals = function( numObj )
    {
    if( (numObj == null) || (buRRRn.Reflection.getTypeOf( numObj ) != "number") )
        {
        return false;
        }
    
    if( this.valueOf() == numObj.valueOf() )
        {
        return true;
        }
    
    return false;
    }

/* StaticProperty: MAX_VALUE
   Returns the largest number representable in ECMAScript (*ECMA-262*).
   
   (code)
   Number.MAX_VALUE = [native code];
   //Number.MAX_VALUE = 1.7976931348623157E+308;
   (end)
*/

/* StaticProperty: MIN_VALUE
   Returns the number closest to zero representable in ECMAScript (*ECMA-262*).
   
   (code)
   Number.MIN_VALUE = [native code];
   //Number.MIN_VALUE = 5.00E-324;
   (end)
*/

/* StaticProperty: NaN
   Special "not a number" value (*ECMA-262*).
   
   (code)
   Number.NaN = [native code];
   (end)
*/

/* StaticProperty: NEGATIVE_INFINITY
   Returns a value more negative than the largest negative number
   (-Number.MAX_VALUE) representable in ECMAScript (*ECMA-262*).
   
   (code)
   Number.NEGATIVE_INFINITY = [native code];
   (end)
*/

/* StaticProperty: POSITIVE_INFINITY
   Returns a value larger than the largest number
   (Number.MAX_VALUE) that can be represented in ECMAScript (*ECMA-262*).
   
   (code)
   Number.POSITIVE_INFINITY = [native code];
   (end)
*/

if( !Number.prototype.toExponential )
    {
    
    /* Method: toExponential
       Returns a string representing the number in exponential notation (*ECMA-262*).
       
       (code)
       Number.prototype.toExponential = function( fractionDigits )
           {
           [native code]
           }
       (end)
       
       attention:
       First implemented in
         - Mozilla JavaScript v1.5
         - Microsoft JScript v5.5
       so we provide a patch for flash ActionScript.
    */
    Number.prototype.toExponential = function( /*int*/ fractionDigits )
        {
        var x, s, str, l, lm, n;
        x = this;
        s = "+";
        
        if( isNaN( x ) )
            {
            return "NaN";
            }
        
        if( x < 0 )
            {
            s = "-";
            x = -x;
            }
        
        if( x == Infinity )
            {
            return s + "Infinity";
            }
        
        l  = Math.floor( Math.log( x ) / Math.LN10 );
        lm = Math.pow( 10, l );
        n  = x / lm;
        
        if( fractionDigits == null )
            {
            str = n.toString();
            }
        else
            {
            if( fractionDigits < 0 )
                {
                fractionDigits = 0;
                }
            else if( fractionDigits > 20 )
                {
                fractionDigits = 20;
                }
            
            str = n.toFixed( fractionDigits );
            }
        
        str += "e" + s + l;
        
        return str;
        }
    
    }

if( !Number.prototype.toFixed )
    {
    
    /* Method: toFixed
       Returns a string representing the number in fixed-point notation (*ECMA-262*).
       
       (code)
       Number.prototype.toFixed = function( fractionDigits )
           {
           [native code]
           }
       (end)
       
       attention:
       First implemented in
         - Mozilla JavaScript v1.5
         - Microsoft JScript v5.5
       so we provide a patch for flash ActionScript.
    */
    Number.prototype.toFixed = function( /*int*/ fractionDigits )
        {
        var x, m, r, str, d, i;
        x = this;
        
        if( isNaN( x ) )
            {
            return "NaN";
            }
        
        if( (fractionDigits == null) || (fractionDigits < 0) )
            {
            fractionDigits = 0;
            }
        else if( fractionDigits > 20 )
            {
            fractionDigits = 20;
            }
        
        m   = Math.pow( 10, fractionDigits );
        r   = Math.round( x*m ) / m;
        str = r.toString();
        d   = str.split( "." )[1];
        
        if( d && (d.length < fractionDigits) )
            {
            for( i=0; i<(fractionDigits-d.length); i++ )
                {
                str += "0";
                }
            }
        
        return str;
        }
    
    }

if( !Number.prototype.toPrecision )
    {
    
    /* Method: toPrecision
       Returns a string representing the number to a specified precision
       in fixed-point notation (*ECMA-262*).
       
       (code)
       Number.prototype.toPrecision = function( precision )
           {
           [native code]
           }
       (end)
       
       attention:
       First implemented in
         - Mozilla JavaScript v1.5
         - Microsoft JScript v5.5
       so we provide a patch for flash ActionScript.
    */
    Number.prototype.toPrecision = function( /*int*/ precision )
        {
        var x, l, m, r, str, d, i;
        x   = this;
        str = x.toString();
        
        if( isNaN( x ) )
            {
            return "NaN";
            }
        
        if( (precision == null) || (x == Infinity) || (x == -Infinity) )
            {
            return this.toString();
            }
        
        if( precision < 1 )
            {
            precision = 1;
            }
        else if( precision > 21 )
            {
            precision = 21;
            }
        
        if( str.length > precision )
            {
            return x.toExponential( precision - 1 );
            }
        
        l   = Math.floor( Math.log(x) / Math.LN10 );
        m   = Math.pow( 10, l + 1 - precision );
        r   = Math.round( x/m ) * m;
        str = r.toString();
        d   = str.split( "." ).join( "" );
        
        if( d && (d.length < precision) )
            {
            if( str.indexOf( "." ) == -1 )
                {
                str += ".";
                }
            
            for( i=0; i<(precision-d.length); i++ )
                {
                str += "0";
                }
            }
        
        return str;
        }
    
    }

/* Method: toSource
   Returns a string representing the source code of the number.
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   (code)
   Number.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   Number.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: Object
   Provides functionality common to all ECMAScript objects.
   
   Object is the primitive ECMAScript object type, and so
   all ECMAScript objects are descended from Object.
   
   that means, all the methods and properties of the
   Object object are available in all other objects.
   
   note:
   the Object object and all other objects implements
   ICloneable, IConvertible, ICopyable, IEquality, IFormattable and ISerializable.
*/

/* Method: clone
   Returns a copy by reference of this object.
   
   see: <ICloneable>
*/
Object.prototype.clone = function()
    {
    return this;
    }

/* Property: constructor
   Specifies the function that creates an object (*ECMA-262*).
   
   note:
   The constructor property contains a reference
   to the function that constructs instances of that particular object.
   
   (code)
   Object.prototype.constructor = [native code]
   (end)
*/

/* Method: copy
   Returns a copy by value of this object.
   
   see: <ICopyable>
*/
Object.prototype.copy = function()
    {
    var obj, member;
    obj = {};
    
    for( member in this )
        {
        if( !this.hasOwnProperty( member ) )
            {
            continue;
            }
        
        if( this[member] === undefined )
            {
            obj[member] = undefined;
            continue;
            }
        
        if( this[member] === null )
            {
            obj[member] = null;
            continue;
            }
        
        obj[member] = this[member].copy();
        }
    
    return obj;
    }

/* Method: equals
   Determines whether two Object instances are equal.
   
   Compare if two objects are equal by value.
   
   see: <IEquality>
*/
Object.prototype.equals = function( obj )
    {
    var member;
    
    if( buRRRn.Reflection.getTypeOf( obj ) == "function" )
        {
        return obj.equals( this );
        }
    
	if( (this.valueOf() == null) && (obj == null) )
		{
		return true;
		}
    
    if( (obj == null) || (buRRRn.Reflection.getTypeOf( obj ) != "object") )
        {
        return false;
        }
    
    if( this == obj )
        {
        return true;
        }
    
    for( member in this )
        {
        /* note:
           by convention we consider members starting with __
           to be internal properties which should not be compared.
        */
        if( member.startsWith( "__" ) )
            {
            continue;
            }
        
        if( !this[member].equals( obj[member] ) )
            {
            return false;
            }
        }
    
    return true;
    }

/* Method: hasOwnProperty
   Returns a Boolean value indicating whether an object
   has a property with the specified name (*ECMA-262*).
   
   attention:
   This method does not check if the property exists
   in the object's prototype chain.
   
   The property must be a member of the object itself.
   
   (code)
   Object.prototype.hasOwnProperty = function( /String/ name )
       {
       [native code]
       }
   (end)
*/

/* Method: hasProperty
   Returns a Boolean value indicating whether an object
   has a property with the specified name (*ECMA-262*).
   
   Returns true whether the property is in the prototype chain or not.
*/
Object.prototype.hasProperty = function( /*String*/ name )
    {
    return( this[name] != undefined );
    }

if( !Object.prototype.isPrototypeOf )
    {
    
    /* Method: isPrototypeOf
       Returns a Boolean value indicating whether an object exists
       in another object's prototype chain.
       
       (code)
       Object.prototype.isPrototypeOf = function( /Object/ value )
           {
           [native code]
           }
       (end)
       
       attention:
       First implemented in
         - Mozilla JavaScript v? (anyone know ?)
         - Microsoft JScript v5.5
         - Macromedia Flash Player v5.0
       so we provide a patch for earlier versions,
       mainly for JScript v5.0 and for Safari.
       
       note:
       We will not support hosts not implementing
       the "instanceof" operator.
       First, because it's impossible to implement
       an operator, and second to implement the functionality
       as a function will be based on the non-standard
       "__proto__" property and can not work everywhere,
       third, "instanceof" is a reserved keyword since
       ECMA-262 2nd edition.
       
    */
    Object.prototype.isPrototypeOf = function( /*Object*/ value )
        {
        var self = this.constructor;
        
        if( typeof value != "object" )
            {
            return false;
            }
        
        if( value instanceof self )
            {
            return true;
            }
        else
            {
            return false;
            }
        }
    
    }


/* Method: memberwiseClone
   Creates a shallow copy of the current Object.
   
   note:
   primitives are copied by value
   and constructible objects are copied by reference.
   
   attention:
   We could have make memberwiseClone a copy of the clone method
   but we didn't because we want only the members to be copied
   by reference, not the container object itself.
*/
Object.prototype.memberwiseClone = function()
    {
    var obj, member;
    obj = {};
    
    for( member in this )
        {
        obj[member] = this[member];
        }
    
    return obj;
    }

/* Method: memberwiseCopy
   Returns a copy by value of this object.
   
   note:
   We want to define this method in the Object prototype
   to inherit it in all the others objects,
   that way if the Object prototype *copy* method get overrided
   we will still be able to use *memberwiseCopy*.
*/
Object.prototype.memberwiseCopy = Object.prototype.copy;

if( !Object.prototype.propertyIsEnumerable )
    {
    
    /* Method: propertyIsEnumerable
       Returns a Boolean value indicating whether
       a specified property is part of an object and if it is enumerable.
       
       (code)
       Object.prototype.propertyIsEnumerable = function( /String/ name )
           {
           [native code]
           }
       (end)
       
       attention:
       First implemented in
         - Mozilla JavaScript v? (anyone know ?)
         - Microsoft JScript v5.5
       so we provide a patch for earlier versions,
       mainly for JScript v5.0 and for Safari.
       
       The patch will not work for JScript version earlier than v5.0
       (no for..in statement).
    */
    Object.prototype.propertyIsEnumerable = function( /*String*/ name )
        {
        
        for( var member in this )
            {
            /* note:
               see ECMA-262
               15.2.4.7 Object.prototype.propertyIsEnumerable
               "This method does not consider objects in the prototype chain."
            */
            if( this.hasOwnProperty( name ) && (member == name) )
                {
                return true;
                }
            }
        
        return false;
        }
    
    }

/* Method: referenceEquals
   Determines whether the specified Object instance
   is the same instance as the current object.
*/
Object.prototype.referenceEquals = function( obj )
    {
	if( (this.valueOf() === null) && (obj === null) )
		{
		return true;
		}

    if( this === obj )
        {
        return true;
        }
    
    if( (obj == null) || (buRRRn.Reflection.getTypeOf( obj ) != "object") )
        {
        return false;
        }
    
	if( this !== obj )
		{
        return false;
		}

	return true;
    }

/* Method: toSource
   Returns a string representing the source code of the object.
   
   Parameters:
   indent   - optionnal, the starting amount of indenting
   indentor - optionnal, the string value used to do the indentation
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
   
   a little note about parameters
   indent can still be passed to toSource
   indentor will be found in <buRRRn.eden.indentor>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   (code)
   Object.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   Object.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Constructor: String
   An object representing a series of characters in a text string.
   
   attention:
   Some methods of the String object have been intentionally
   ignored because it feels like they should relate to a custom
   HTMLString object.
   
   here the list: anchor, big, blink, bold, fixed, fontcolor,
   fontsize, italics, link, small, strike, sub, and sup.
   
   attention:
   Some other methods have been ignored because of
   their relation with the RegExp object (match, search).
*/

/* Method: charAt
   Returns the character at the specified index (*ECMA-262*).
   
   note:
   Values of index out of valid range return an empty string.
   
   (code)
   String.prototype.charAt = function( index )
       {
       [native code]
       }
   (end)
*/

/* Method: charCodeAt
   Returns a number indicating the Unicode value of
   the character at the given index (*ECMA-262*).
   
   note:
   If there is no character at the specified index,
   NaN is returned.
   
   (code)
   String.prototype.charCodeAt = function( index )
       {
       [native code]
       }
   (end)
*/

/* Method: clone
   Returns a copy by reference of this string.
   
   attention:
   If the instance is a primitive the behaviour
   is to return a copy by value.
   
   exemple:
   (code)
   str1 = new String( "hello world" );
   str2 = str1.clone(); //reference copy
   
   str3 = "hello world";
   str4 = str3.clone(); //not a reference but a primitive value copy
   (end)
*/
String.prototype.clone = function()
    {
    return this;
    }

/* StaticMethod: compare
   Compares the two specified String objects.
   
   Parameters:
     strA       - first string to compare
     strB       - with second string
     ignoreCase - optionnal, allow to take into account the case for comparison
*/
String.compare = function( /*String*/ strA, /*String*/ strB, /*Boolean*/ ignoreCase )
    {
    if( (strA == null) || (strB == null) )
        {
        if( strA == strB )
            {
            return 0; //both null
            }
        else if( strA == null )
            {
            return -1; //strA is null -1
            }
        else
            {
            return 1; //strB is null 1
            }
        //return (strA == null) ? -1 : 1; // a is null -1, B is null 1
        }
    
    if( (buRRRn.Reflection.getTypeOf( strA ) != "string") || (buRRRn.Reflection.getTypeOf( strB ) != "string") )
        {
        return; //ArgumentStringExpected
        }
    
    //we force conversion to a string primitive type
    /*!## TODO: use valueOf method ? */
    strA = strA.toString();
    strB = strB.toString();
    
    if( ignoreCase == true )
        {
        strA = strA.toLowerCase();
        strB = strB.toLowerCase();
        }
    
    if( strA == strB )
        {
        return 0;
        }
    else if( strA.length > strB.length )
        {
        return 1;
        }
    else
        {
        return -1;
        }
    }

/* Method: compareTo
   Compares this instance with a specified Object.
   
   note:
   returns value are
   less than zero       -  this instance is less than value
   zero                 -  this instance is equal to value
   greater than zero    -  this instance is greater than value (or value is null)
*/
String.prototype.compareTo = function( value )
    {
    
    if( value == null )
        {
        return 1;
        }
    
    if( buRRRn.Reflection.getTypeOf( value ) != "string" )
        {
        return; //ArgumentException - value must be string
        }
    
    return String.compare( this.valueOf(), value.valueOf() );
    }

/* Method: concat
   Returns a string value containing the concatenation
   of two or more supplied strings (*ECMA-262*).
   
   note:
   If any of the arguments are not strings, they are first
   converted to strings before being concatenated.
   
   (code)
   String.prototype.concat = function( ... )
       {
       [native code]
       }
   (end)
*/

/* Method: copy
   Returns a copy by value of this object.
   
   note:
   this method always return a primitive.
*/
String.prototype.copy = function()
    {
    return this.valueOf();
    }

/* Method: equals
   Determines if this instance is equal to a String value.
*/
String.prototype.equals = function( strObj )
    {
    if( (strObj == null) || (buRRRn.Reflection.getTypeOf( strObj ) != "string") )
        {
        return false;
        }
    
    /* note: we force a string primitive type */
    /*!## TODO: use valueOf ? */
    if( this.toString() == strObj.toString() )
        {
        return true;
        }
    
    return false;
    }

/* StaticProperty: empty
   Represents the empty string.
   
   This property should be read-only.
*/
String.empty = "";

/* Method: endsWith
   Determines whether the end of this instance matches the specified String.
*/
String.prototype.endsWith = function( /*String*/ value )
    {
    if( value == null )
        {
        return false;
        }
    
    if( this.length < value.length )
        {
        return false;
        }
    
    return String.compare( this.substr( this.length-value.length ), value) == 0;
    }

/* StaticMethod: format
   Replaces the format item in a specified String with
   the text equivalent of the value of a specified Object instance.
   
   usage:
   (code)
   String.format( "...", obj )
   String.format( "...", [obj0, obj1, obj2, obj3, ...] )
   String.format( "...", obj0, obj1, obj2, obj3, ... )
   (end)
   
   Parameters:
   about the format parameters *{index[,alignment][:formatString]}*
         
     index       -  a zero-based integer
                    (if equal null or undefined will be replaced by
                    the empty string).
     
     alignment   -  optionnal, integer which specify the minimum width
                    of the region to contain the formated value.
                    if the length of the value is less than the alignment
                    then the region is padded with spaces.
                    if alignment is negative then the value is left justified.
                    if alignment is positive then the value is right justified.
                    the comma *,* is required if alignment is specified.
                    
     formatString - optional, string of formating code.
                    the colon *:* is required if formatString is specified.
                    the default formatString is the space chars.
         
   exemple:
   (code)
   var test = String.Format( "Brad's dog has {0,-8:_} fleas.", 42 );
   trace( test ); //output: "Brad's dog has 42______ fleas."
   
   var test = String.Format( "Brad's dog has {0,-8:.} fleas.", 42 );
   trace( test ); //output: "Brad's dog has 42...... fleas."
   
   var test = String.Format( "Brad's dog has {0,8:.} fleas.", 42 );
   trace( test ); //output: "Brad's dog has ......42 fleas."
   
   var test = String.Format( "Brad's dog has {0,-8} fleas.", 42 );
   trace( test ); //output: "Brad's dog has 42       fleas."
   (end)
   
   note:
   if the format is malformed as
   (code)
   String.Format( "Brad's dog has {0:_} fleas.", 42 );
   (end)
   the malformed part is ignored and interpreted as
   (code)
   String.Format( "Brad's dog has {0} fleas.", 42 );
   (end)
   
   except if the chars after the colon can be converted to a number
   (code)
   String.Format( "Brad's dog has {0:10} fleas.", 42 );
   (end)
   
   in this case the format is interpreted as
   (code)
   String.Format( "Brad's dog has {0,10} fleas.", 42 );
   (end)
*/
String.format = function( /*String*/ format, /*...*/ argN )
    {
    if( (arguments.length == 0) || (format == "") ||
        ( (format.indexOf( "{" ) == -1) && (format.indexOf( "}" ) == -1) ) )
        {
        return format; //nothing to format
        }
    
    var paddingChar   = " ";
    var indexedValues = [];
    var namedValues   = {};
    
    //parse arguments
    var args = Array.fromArguments( arguments );
    args.shift();
    
    if( args.length >= 1 )
        {
        if( args[0] instanceof Array )
            {
            indexedValues = indexedValues.concat( args[0] );
            args.shift();
            }
        else if( (args[0] instanceof Object) && (String(args[0]) == "[object Object]") )
            {
            for( var prop in args[0] )
                {
                namedValues[ prop ] = args[0][ prop ];
                }
            args.shift();
            }
        }
    
    indexedValues = indexedValues.concat( args );
    
    //escape {{ and }}
    var ORC1 = "\uFFFC"; //Object Replacement Character
    var ORC2 = "\uFFFD"; //Object Replacement Character
    if( format.indexOfAny( [ "{{", "}}" ] ) > -1 )
        {
        format = format.split( "{{{" ).join( ORC1+"{" );
        format = format.split( "{{" ).join( ORC1 );
        format = format.split( "}}}" ).join( "}"+ORC2 );
        format = format.split( "}}" ).join( ORC2 );
        }
    
    var parseExpression = function( expression/*String*/ )/*String*/
        {
        var value      = "";
        var spaceAlign = 0;
        var isAligned  = false;
        var padding    = paddingChar; //default
        
        if( expression.indexOfAny( [ ",", ":" ] ) > -1 )
            {
            var vPos = expression.indexOf( "," );
            if( vPos == -1 )
                {
                trace( "malformed format, could not find [,] before [:]." );
                return "";
                }
            
            var fPos = expression.indexOf( ":" );
            
            if( fPos == -1 )
                {
                spaceAlign = parseInt( expression.substr( vPos+1 ) );
                }
            else
                {
                spaceAlign  = parseInt( expression.substring( vPos+1, fPos ) );
                padding     = expression.substr( fPos+1 );
                }
            
            isAligned  = true;
            expression = expression.substring( 0, vPos );
            }
        
        var c = expression.split("")[0];
        if( (("A" <= c) && (c <= "Z")) || (("a" <= c) && (c <= "z")) )
            {
            value = String( namedValues[ expression ] );
            }
        else if( ("0" <= c) && (c <= "9") )
            {
            value = String( indexedValues[ parseInt(expression) ] );
            }
        
        if( isAligned )
            {
            if( (spaceAlign > 0) && (value.length < spaceAlign) )
                {
                value = value.padLeft( spaceAlign, padding );
                }
            else( -value.length < spaceAlign )
                {
                value = value.padRight( -spaceAlign, padding );
                }
            }
        
        return value;
        }
    
    
    var expression = "";
    var formated   = "";
    var ch  = "";
    var pos = 0;
    var len = format.length;
    
    var next = function()
        {
        ch = format.charAt( pos );
        pos++;
        return ch;
        }
    
    //parsing
    while( pos < len )
        {
        next();
        if( ch == "{" )
            {
            expression = next();
            while( next() != "}" )
                {
                expression += ch;
                }
            formated += parseExpression( expression );
            }
        else
            {
            formated += ch;
            }
        }
    
    if( formated.indexOfAny( [ ORC1, ORC2 ] ) > -1 )
        {
        formated = formated.split( ORC1 ).join( "{" );
        formated = formated.split( ORC2 ).join( "}" );
        }
    
    return formated;
    }

/* StaticMethod: fromCharCode
   Returns a string from a number of Unicode character values (*ECMA-262*).
   
   (code)
   String.fromCharCode = function( ... )
       {
       [native code]
       }
   (end)
*/

/* Method: indexOf
   Returns the character position where the first
   occurrence of a substring occurs within a String object,
   or -1 if not found (*ECMA-262*).
   
   note:
   If startindex is negative, startindex is treated as zero.
   If it is larger than the greatest character position index,
   it is treated as the largest possible index.
   
   (code)
   String.prototype.indexOf = function( /String/ subString, /Int/ startIndex )
       {
       [native code]
       }
   (end)
*/

/* Method: indexOfAny
   Reports the index of the first occurrence in this instance
   of any character in a specified array of characters (or Strings).
   
   Parameters;
     startIndex - optionnal, allow to specifiy the starting index for the search
     count      - optionnal, allow to specify the count of index before ending the search
*/
String.prototype.indexOfAny = function( /*Array*/ anyOf, /*int*/ startIndex, /*int*/ count )
    {
    var i, endIndex;
    
    if( anyOf == null )
        {
        return; //ArgumentNullException
        }
    
    if( this.length == 0 )
        {
        return -1;
        }
    
    if( (startIndex == null) || (startIndex < 0) )
        {
        startIndex = 0;
        }
    
    if( (count == null) || (count < 0) || (count > anyOf.length - startIndex) )
        {
        endIndex =  anyOf.length - 1;
        }
    else
        {
        endIndex = startIndex + count - 1;
        }
    
    for( i=startIndex; i<=endIndex ; i++ )
        {
        if( this.indexOf( anyOf[i] ) > -1 )
            {
            return i;
            }
        }
    
    return -1;
    }

/* Method: insert
   Inserts a specified instance of String at
   a specified index position in this instance.
   
   note:
   if index is null, we directly append the value to the end of the string.
   
   if index is zero, we directly insert it to the begining of the string.
*/
String.prototype.insert = function( /*int*/ startIndex, /*String*/ value )
    {    
    var str, strA, strB;
    str = this.copy();
    
    if( value == null )
        {
        return str;
        }
    
    if( str == "" )
        {
        return value;
        }
    
    if( startIndex == 0 )
        {
        return value + str;
        }
    else if( (startIndex == null) || (startIndex == str.length) )
        {
        return str + value;
        }
    
    strA = str.substr( 0, startIndex );
    strb = str.substr( startIndex );
    
    return strA + value + strB;
    }

/* Method: lastIndexOf
   Returns the last occurrence of a substring within a String object,
   or -1 if not found (*ECMA-262*).
   
   note:
   If startindex is negative, startindex is treated as zero.
   
   If it is larger than the greatest character position index,
   it is treated as the largest possible index.
   
   (code)
   String.prototype.lastIndexOf = function( /String/ subString, /Int/ startIndex )
       {
       [native code]
       }
   (end)
*/

/* Method: lastIndexOfAny
   Reports the index position of the last occurrence in this
   instance of one or more characters specified in an array (*ECMA-262*).
*/
String.prototype.lastIndexOfAny = function( /*Array*/ anyOf, /*Int*/ startIndex, /*Int*/ count )
    {
    var i, endIndex;
    
    if( anyOf == null )
        {
        return; //ArgumentNullException
        }
    
    if( this.length == 0 )
        {
        return -1;
        }
    
    if( (startIndex == null) || (startIndex < 0) || (startIndex > anyOf.length) )
        {
        startIndex = anyOf.length - 1; //ArgumentOutOfRangeException
        }
    
    if( (count == null) || (count < 0) || (count > startIndex+1) )
        {
        endIndex = 0; //ArgumentOutOfRangeException
        }
    else
        {
        endIndex = startIndex - count + 1;
        }
    
    for( i=startIndex; i>= endIndex; i-- )
        {
        if( this.lastIndexOf( anyOf[i] ) > -1 )
            {
            return i;
            }
        }
    
    return -1;
    }

/* Property: length
   Reflects the length of the string (*ECMA-262*).
*/

/*!## Method: localeCompare
   see ECMA-262 specification (ch. 15.5.4.9)
   
   note:
   this method is not implemented in
   most of ECMAScript implementation.
   The compareTo method is an equivalent.
*/

/* PrivateMethod: _PadHelper
   Helper method for the padLeft and padRight method.
*/
String.prototype._padHelper = function( /*int*/ totalWidth, /*char*/ paddingChar, /*Boolean*/ isRightPadded )
    {
    var str, SPC;
    str = this.copy();
    SPC = " ";
    
    if( (totalWidth < str.length) || (totalWidth < 0) )
        {
        return str;
        }
    
    if( paddingChar == null )
        {
        paddingChar = SPC;
        }
    
    /* note:
       we want to limit the string to ONLY ONE char
    */
    if( paddingChar.length > 1 )
        {
        paddingChar = paddingChar.charAt( 0 );
        }
    
    while( str.length != totalWidth )
        {
        if( isRightPadded == true )
            {
            str += paddingChar;
            }
        else
            {
            str = paddingChar + str;
            }
        }
    
    return str;
    }

/* Method: padLeft
   Right-aligns the characters in this instance,
   padding with paddingChar (or spaces if not precised)
   on the left for a specified total length.
*/
String.prototype.padLeft = function( /*int*/ totalWidth, /*char*/ paddingChar )
    {
    return this._padHelper( totalWidth, paddingChar, false);
    }

/* Method: padRight
   Left-aligns the characters in this string,
   padding with paddingChar (or spaces if not precised)
   on the right for a specified total length.
*/
String.prototype.padRight = function( /*int*/ totalWidth, /*char*/ paddingChar )
    {
    return this._padHelper( totalWidth, paddingChar, true);
    }

if( !String.prototype.replace )
    {
    
    /* Method: replace
       Replaces all occurrences of a specified String
       in this instance, with another specified String (*ECMA-262*).
       
       note:
       the result of the replace method is a copy of the string
       object after the specified replacement has been made.
       
       attention:
       First implemented in
         - Mozilla JavaScript v1.2
         - Microsoft JScript v1.0
       so we provide a patch for flash ActionScript.
    */
    String.prototype.replace = function( /*String*/ oldValue , /*String*/ newValue )
        {
        if( (oldValue == null) || (oldValue.length == 0) )
            {
            return this.toString();
            }
        
        if( newValue == null )
            {
            newValue = "";
            }
        
        if( this.indexOf( oldValue ) > -1 )
            {
            return this.split( oldValue ).join( newValue );
            }
        
        return this;
        }

    }

/* Method: slice
   Extracts a section of a string and returns a new string (*ECMA-262*).
   
   note:
   The slice method copies up to, but not including,
   the element indicated by end.
   
   If start is negative, it is treated as length + start
   where length is the length of the string.
   
   If end is negative, it is treated as length + end
   where length is the length of the string.
   
   If end is omitted, extraction continues to the end
   of the string object.
   
   If end occurs before start,
   no characters are copied to the new string.
   
   (code)
   String.prototype.slice = function( /int/ start, /int/ end )
       {
       [native code]
       }
   (end)
*/

/* Method: split
   Returns the array of strings that results when
   a string is separated into substrings (*ECMA-262*).
   
   (code)
   String.prototype.split = function( /String/ separator, /int/ limit )
       {
       [native code]
       }
   (end)
*/

/* Method: startsWith
   Determines whether a specified string is a prefix
   of the current instance.
*/
String.prototype.startsWith = function( /*String*/ value )
    {
    if( value == null )
        {
        return false;
        }
    
    if( this.length < value.length )
        {
        return false;
        }
    
    if( this.charAt( 0 ) != value.charAt( 0 ) )
        {
        return false;
        }
    
    return( String.compare( this.substr( 0, value.length), value) == 0);
    }

/* Method: substr
   Returns a substring beginning at a specified location
   and having a specified length 
   (not defined in the ECMA-262 specifications).
   
   note:
   If length is zero or negative, an empty string is returned.
   If not specified, the substring continues to the end of
   the current string.
   
   (code)
   String.prototype.substr = function( /int/ start, /int/ length )
       {
       [native code]
       }
   (end)
*/

/* Method: substring
   Returns the characters in a string between two
   indexes into the string (*ECMA-262*).
   
   note:
   The substring method returns a string containing the
   substring from start up to, but not including, end.
   
   If either start or end is NaN or negative,
   it is replaced with zero.
   
   (code)
   String.prototype.substring = function( /int/ start, /int/ end )
       {
       [native code]
       }
   (end)
*/

/* Method: toBoolean
   Converts to an equivalent Boolean value.
*/
String.prototype.toBoolean = function()
    {
    if( this.length == 0 )
        {
        return false;
        }
    
    return true;
    }

/* Method: toCharArray
   Copies the characters in this instance to
   a character array.
   
   note:
   we don't have yet a *char* constructor so we build
   an Array composed of String.
*/
String.prototype.toCharArray = function( /*int*/ startIndex, /*int*/ count )
    {
    var arr;
    arr = [];
    
    if( this == "" )
        {
        return arr;
        }
    
    if( (startIndex < 0) || (startIndex == null) ||
        (startIndex > this.length) || (startIndex > this.length - count) )
        {
        startIndex = 0;
        }
    
    if( (count <= 0) || (count == null) )
        {
        startIndex = 0;
        count      = this.length;
        }
    
    arr = this.split( "" );
    
    if( (startIndex != 0) || (count != this.length) )
        {
        arr = arr.splice( startIndex, count )
        }
    
    return arr;
    }

/* Method: toLowerCase
   Returns a string where all alphabetic characters
   have been converted to lowercase.
   
   (code)
   String.prototype.toLowerCase = function()
       {
       [native code]
       }
   (end)
*/

/* Method: toSource
   Returns a string representing the source code of the object.
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* Method: toString
   Returns a string representing the specified object (*ECMA-262*).
   
   (code)
   String.prototype.toString = function()
       {
       [native code]
       }
   (end)
*/

/* Method: toUpperCase
   Returns a string where all alphabetic characters
   have been converted to uppercase (*ECMA-262*).
   
   (code)
   String.prototype.toUpperCase = function()
       {
       [native code]
       }
   (end)
*/

/* PrivateMethod: _trimHelper
   Helper method used by trim, trimStart and trimEnd methods.
*/
String.prototype._trimHelper = function( /*Array*/ trimChars, /*Boolean*/ trimStart, /*Boolean*/ trimEnd )
    {
    if( trimStart == null )
        {
        trimStart = false;
        }
    
    if( trimEnd == null )
        {
        trimEnd = false;
        }
    
    var str, iLeft, iRight;
    str = this.copy();
    
    if( trimStart )
        {
        for( iLeft=0; (iLeft<str.length) && (trimChars.contains( str.charAt( iLeft ) )); iLeft++ )
            {
            }
        
        str = str.substr( iLeft );
        }
    
    if( trimEnd )
        {
        for( iRight=str.length-1; (iRight>=0) && (trimChars.contains( str.charAt( iRight ) )); iRight-- )
            {            
            }
        
        str = str.substring( 0, iRight+1 );
        }
    
    return str;
    }

/* Method: trim
   Removes all occurrences of a set of specified characters (or strings)
   from the beginning and end of this instance.
*/
String.prototype.trim = function( /*Array*/ trimChars )
    {
    if( (trimChars == null) || (trimChars.length == 0) )
        {
        trimChars = String.whiteSpaceChars;
        }
    
    return this._trimHelper( trimChars, true, true );
    }

/* Method: trimEnd
   Removes all occurrences of a set of characters specified
   in an array from the end of this instance.
*/
String.prototype.trimEnd = function( /*Array*/ trimChars )
    {
    if( (trimChars == null) || (trimChars.length == 0) )
        {
        trimChars = String.whiteSpaceChars;
        }
    
    return this._trimHelper( trimChars, null, true );
    }

/* Method: trimStart
   Removes all occurrences of a set of characters specified
   in an array from the beginning of this instance.
*/
String.prototype.trimStart = function( /*Array*/ trimChars )
    {
    if( (trimChars == null) || (trimChars.length == 0) )
        {
        trimChars = String.whiteSpaceChars;
        }
    
    return this._trimHelper( trimChars, true );
    }

/* Method: valueOf
   Returns the primitive value of the specified object (*ECMA-262*).
   
   (code)
   String.prototype.valueOf = function()
       {
       [native code]
       }
   (end)
*/

/* StaticProperty: whiteSpaceChars
   Contains a list of white space chars.
   
   This property should be read-only.
*/
String.whiteSpaceChars = [ "\u0009", "\u000A", "\u000B", "\u000C", "\u000D",
                           "\u0020", "\u00A0", "\u2000", "\u2001", "\u2002",
                           "\u2003", "\u2004", "\u2005", "\u2006", "\u2007",
                           "\u2008", "\u2009", "\u200A", "\u200B", "\u3000",
                           "\uFEFF" ];


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* NameSpace: _global
   An intrinsic object whose purpose is to collect
   global methods into one object.
   
   The Global object has no syntax.
   
   You call its methods directly.
   
   note:
   The Global object is never used directly, and cannot be
   created using the new operator.
   
   It is created when the scripting engine is initialized,
   thus making its methods and properties available immediately.
   
   attention:
   The implementation and use of the Global object is different
   depending the environment, here we have chosen to name it
   *_global* to signify its hidden nature.
*/

/* GlobalFunction: escape
   Encodes String objects so they can be read on all computers (*ECMA-262*).
   
   note:
   The escape method returns a string value (in Unicode format)
   that contains the contents of charstring.
   
   All spaces, punctuation, accented characters, and any other
   non-ASCII characters are replaced with %xx encoding, where
   xx is equivalent to the hexadecimal number representing the character.
   
   For example, a space is returned as "%20."
   
   Characters with a value greater than 255 are stored using the %uxxxx format.
   
   (code)
   _global.escape = function( /String/ value )
       {
       [native code]
       }
   (end)
*/

/* GlobalFunction: eval
   Evaluates ECMAScript code and executes it (*ECMA-262*).
   
   note:
   The eval function allows dynamic execution of ECMAScript source code.
   
   In some environment this function is not fully implemented,
   for example: ActionScript.
   
   (code)
   _global.eval = function( /String/ codeString )
       {
       [native code]
       }
   (end)
*/

/* GlobalFunction: hasOwnProperty
   _global scope does not inherit from the Object scope
   the hasOwnProperty method so we create it.
   
   see: <Object.hasOwnProperty>
*/
_global.hasOwnProperty = Object.prototype.hasOwnProperty;

/* GlobalProperty: Infinity
   Returns an initial value of Number.POSITIVE_INFINITY (*ECMA-262*).
   
   (code)
   _global.Infinity = [native code];
   (end)
*/

/* GlobalFunction: isFinite
   Returns a Boolean value that indicates
   if a supplied number is finite (*ECMA-262*).
   
   note:
   The isFinite method returns true if number is any value
   other than NaN, negative infinity, or positive infinity.
   
   In those three cases, it returns false.
   
   (code)
   _global.isFinite = function( /Number/ value )
       {
       [native code]
       }
   (end)
*/

/* GlobalFunction: isNaN
   Returns a Boolean value that indicates whether
   a value is the reserved value NaN (not a number) (*ECMA-262*).
   
   note:
   The isNaN function returns true if the value is NaN,
   and false otherwise.
   
   You typically use this function to test return values
   from the parseInt and parseFloat methods.
   
   Alternatively, a variable could be compared to itself.
   
   If it compares as unequal, it is NaN. This is because NaN
   is the only value that is not equal to itself.
   
   (code)
   _global.isNaN = function( value )
       {
       [native code]
       }
   (end)
*/

/* GlobalProperty: NaN
   Returns the special value NaN indicating that
   an expression is not a number (*ECMA-262*).
   
   (code)
   _global.NaN = [native code];
   (end)
*/

/* GlobalFunction: parseFloat
   Returns a floating-point number converted from a string (*ECMA-262*).
   
   note:
   The parseFloat method returns a numerical value equal to
   the number contained in numString.
   
   If no prefix of numString can be successfully parsed
   into a floating-point number, NaN (not a number) is returned.
   
   (code)
   _global.parseFloat = function( /String/ value )
       {
       [native code]
       }
   (end)
*/

/* GlobalFunction: parseInt
   Returns an integer converted from a string (*ECMA-262*).
   
   note:
   The parseInt method returns an integer value equal to the number
   contained in numString.
   
   If no prefix of numString can be successfully parsed into an integer,
   NaN (not a number) is returned.
   
   attention:
   Radix can be a value between 2 and 36 indicating the base of the
   number contained in numString.
   
   If not supplied, strings with a prefix of '0x' are considered hexadecimal
   and strings with a prefix of '0' are considered octal.
   
   All other strings are considered decimal.
   
   (code)
   _global.parseInt = function( /String/ value, /int/ radix )
       {
       [native code]
       }
   (end)
*/

/* GlobalFunction: propertyIsEnumerable
   _global scope does not inherit from the Object scope
   the propertyIsEnumerable method so we create it.
   
   see: <Object.propertyIsEnumerable>
*/
_global.propertyIsEnumerable = Object.prototype.propertyIsEnumerable;

/* GlobalFunction: ToSource
   Allow you to dump the source of the Global Object scope.
   
   example:
   (code)
   trace( ToSource( 0 ) );
   (end)
   
   deprecated:
   see <buRRRn.eden> and option <buRRRn.core2.config.allowToSource>
*/

/* GlobalFunction: trace
   Outputs text to either a message box or a console window.
   
   note:
   Here we force a cast to string to allways return the string
   representation of the object.
   
   attention:
   This function is dependent on the ECMAScript host.
   
   For browsers it will trace either in an alert window or a DIV layer.
   
   For flash it will trace to the output window.
   
   For tools as WSH/JSDB it will trace to the prompt.
   
   Look at the core2.HOST_EXTENSION file to see the implementation.
*/

/* GlobalFunction: unescape
   Decodes String objects encoded with the escape method (*ECMA-262*).
   
   (code)
   _global.unescape = function( /String/ value )
       {
       [native code]
       }
   (end)
*/


/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

if( !_global.buRRRn.Reflection )
    {
    /* Singleton: Reflection
       Provide utility function for reflection mecanism in ECMA-262.
       
    */
    _global.buRRRn.Reflection = {};
    }

/* property: memoize
   Allows to save objects path in 
   a special __path__ property
*/
buRRRn.Reflection.memoize = false;

/* Method: getTypeOf
   Returns the type of the passed object.
*/
buRRRn.Reflection.getTypeOf = function( o )/*String*/
    {
    if( o === undefined )
        {
        return "undefined";
        }
    
    if( o === null )
        {
        return "null";
        }
    
    switch( o.constructor )
        {
        case Array:    return "array";
        case Boolean:  return "boolean";
        case Date:     return "date";
        case Error:    return "error";
        case Function: return "function";
        case Number:   return "number";
        case String:   return "string";
        case Object:   return "object";
        default:       return( typeof o );
        }
    }


/* Method: getCoreObjectPath
*/
buRRRn.Reflection.getCoreObjectPath = function( o )/*String*/
    {
    switch( o )
        {
        case Array:    return "Array";
        case Boolean:  return "Boolean";
        case Date:     return "Date";
        case Error:    return "Error";
        case Function: return "Function";
        case Number:   return "Number";
        case String:   return "String";
        case Object:   return "Object";
        }
    
    return undefined;
    }

/* Method: getConstructorPath
   Returns the constructor path of the instance as string.
*/
buRRRn.Reflection.getConstructorPath = function( o )/*String*/
    {
    if( o == _global )
        {
        return "Object";
        }
    /*
    switch( o.constructor )
        {
        case Array:    return "Array";
        case Boolean:  return "Boolean";
        case Date:     return "Date";
        case Error:    return "Error";
        case Function: return "Function";
        case Number:   return "Number";
        case String:   return "String";
        case Object:   return "Object";
        }
    */
    var path = this.getObjectPath( o.constructor );
    
    if( path == undefined )
        {
        path = "Object"; //by default any ECMAScript objects inherit from object Object
        }
    
    return path;
    }

/* Method: getConstructorName
   Returns the constructor name of the current instance as string.
*/
buRRRn.Reflection.getConstructorName = function( o )/*String*/
    {
    var path = this.getConstructorPath( o );
    
    if( path.indexOf( "." ) > -1 )
        {
        path = path.split( "." );
        return path.pop();
        }
    
    return path;
    }

/* Method: 
   Returns the constructor reference from a string constructor name.
*/
buRRRn.Reflection.getConstructorByName = function( name/*String*/ )/*Function*/
    {
    var path;
    var original = name;
    
    if( name.indexOf(".") > -1 )
        {
        path = name.split( "." );
        }
    else
        {
        path = [ name ];
        }
    
    var root = path.shift();
    var ref = _global[ root ];
    
    if( ref == undefined )
        {
        throw new Error( "_global."+original+" does not exists" );
        }
    
    
    for( var i=0; i<path.length; i++ )
        {
        ref = ref[ path[i] ];
        
        if( ref == undefined )
            {
            throw new Error( "_global."+original+" does not exists" );
            }
        }
    
    if( typeof ref == "function" )
        {
        return ref;
        }
    else
        {
        throw new Error( "_global."+original+" is not a function constructor" );
        }
    }

buRRRn.Reflection.getConstructorMethods = function( o, inherited/*Boolean*/ )/*Array*/
    {
    if( inherited == null )
        {
        inherited = false;
        }
    
    var member;
    var members = [];
    
    for( member in o.prototype )
        {
        if( typeof o.prototype[member] == "function" )
            {
            if( inherited || (o === Object) )
                {
                members.push( member );
                }
            else if( o.prototype[member] != Object.prototype[member] )
                {
                members.push( member );
                }
            }
        }
    
    return members;
    }

buRRRn.Reflection.getObjectMethods = function( o )/*Array*/
    {
    var member;
    var members = [];
    
    for( member in o )
        {
        if( typeof o[member] == "function" )
            {
            if( (o !== Object) &&
                (o[member] !== Object.prototype[member]) &&
                (o[member] !== Object[member]) )
                {
                members.push( member );
                }
            else if( (o === Object) &&
                     (o[member] !== Object.prototype[member]) &&
                     (o[member] !== Function.prototype[member]) )
                {
                members.push( member );
                }
            }
        }
    
    return members;
    }

buRRRn.Reflection.getMethodByName = function( o, name/*String*/ )/*Function*/
    {
    var methods  = this.getConstructorMethods( o );
    var omethods = this.getObjectMethods( o );
    
    if( methods.indexOf( name ) > -1 )
        {
        return o.prototype[name];
        }
    
    if( omethods.indexOf( name ) > -1 )
        {
        return o[name];
        }
    
    return null;
    }

/* Method: hasConstructorByName
   Returns a boolean telling if the constructor exists from a string name.
*/
buRRRn.Reflection.hasConstructorByName = function( name/*String*/ )/*Boolean*/
    {
    try
        {
        var ctor = this.getConstructorByName( name );
        }
    catch( e )
        {
        return false;
        }
    
    return true;
    }

/* Method: getObjectPath
   Returns the string path of the target object.
   
   Parameters:
     target - un object target path 
     scope  - optional, allow you to scan members in an object scope
   
   note:
   You can only retrieve path of enumerable objects defined in _global,
   objects marked as DontEnum are not resolved,
   internal and build-in objects are in general marked as DontEnum.
   
   You will not be able to resolve path of local variable in function scope.
*/
buRRRn.Reflection.getObjectPath = function( target/*Object*/, scope )/*String*/
    {
    var maxRecursion, commands, values, refs, name, ref, scopePath, isCoreObject, m, mm;
    maxRecursion = 200; //better if < 0xFF
    commands     = [];
    values       = [];
    refs         = [];
    scopePath    = "";
    
    if( target == null )
        {
        return undefined;
        }
    
    if( target === _global )
        {
        return "_global";
        }
    
    isCoreObject = this.getCoreObjectPath( target );
    if( isCoreObject != undefined )
        {
        return isCoreObject;
        }
    
    if( scope == null )
        {
        scope = _global; //by default the scope to scan is global
        }
    else
        {
        scopePath = this.getCoreObjectPath( scope );
        
        if( scopePath == undefined )
            {
            scopePath = this.getObjectPath( scope );
            }
        
        }
    
    //path already found
    if( target.__path__ )
        {
        return target.__path__;
        }
    
    /* internalFunction: list
    */
    var list = function()
        {
        name = values.pop();
        ref  = refs.pop();
        
        if (ref == null)
            {
            values.push( "" );
            }
        else
            {
            
            for( m in ref )
                {
                /* attention:
                   if the host does not mark "prototype"
                   as DontEnum (as it should be!)
                   this can cause recursions errors,
                   so we want to avoid that.
                */
                if( m == "prototype" )
                    {
                    continue;
                    }
                
                /* attention:
                   we do not want to itterate trough Array indexes,
                   especially with Mozilla JavaScript as
                   <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:String>
                   indicate that string can be accessed as array
                   ex: 'cat'[1] // returns "a"
                */
                if( (ref[m] != null) && (ref[m].constructor == Array) )
                    {
                    continue;
                    }
                
                /* note:
                   We want to scan only objects and functions,
                   the only type being able to contain child members.
                */
                if( ((typeof(ref[m]) == "object") || (typeof(ref[m]) == "function")) &&
                    (ref.hasOwnProperty( m )) )
                    {
                    commands.push( list );
                    values.push( name + "." + m );
                    refs.push( ref[m] );
                    }
                
                }
            }
        }
    
    for( mm in scope )
        {
        /* attention:
           We do not want to scan global reserved objects,
           especially for browsers where it cause recursion errors.
        */
        if( buRRRn.core2.isGlobalReserved( mm ) )
            {
            continue;
            }
        
        commands.push( list );
        values.push( mm );
        refs.push( scope[mm] );
        }
    
    if( scope == _global )
        {
        var i, coreObjects, coreObject;
        coreObjects = ["Array","Boolean","Date","Error","Function","Number","String","Object"]
        
        for( i=0; i<coreObjects.length; i++ )
            {
            coreObject = coreObjects[i];
            
            commands.push( list );
            values.push( coreObject );
            refs.push( scope[coreObject] );
            }
        }
    
    while( (commands.length != 0) && (commands.length < maxRecursion ) )
        {
        commands.pop()();
        
        if( ref === target ) //we want to test identity!!!
            {
            /* note:
               Here we save the result of the path
               to not recompute it later.
               see: <http://www.nist.gov/dads/HTML/memoize.html>
            */
            if( this.memoize && (scope == _global) )
                {
                target.__path__ = name;
                }
            
            return scopePath+name;
            }
        }
    
    return undefined;
    }





/*
  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is core2: ECMAScript core objects 2nd gig. 
  
  The Initial Developer of the Original Code is
  Zwetan Kjukov <zwetan@gmail.com>.
  Portions created by the Initial Developer are Copyright (C) 2003-2007
  the Initial Developer. All Rights Reserved.
  
  Contributor(s):
*/

/* Singleton: Operators
*/
buRRRn.Operators = {};

/* Method: is
   Allow to test the type of an instance.
   
   note:
   typing typeof is long
   (code)
   if( typeof instance == "string" )
   //...
   (end)
   typeof is limited in certain case
   (code)
   var txt = new String( "hello world" );
   if( typeof txt == "string" ) //does not match
       {
       //...
       }
   (end)
   to fully test you would need
   (code)
   var txt = new String( "hello world" );
   if( (typeof txt == "string") || (txt instanceof String) ) //does match
       {
       //...
       }
   (end)
   
   usage:
   (code)
   var txt = new String( "hello world" );
   
   if( is(txt)(String) )
       {
       //...
       }
   
   //or
   
   if( is(txt)("String") ) //case sensitive
       {
       //...
       }
   
   (end)
*/
buRRRn.Operators.is = function( o )/*Function*/
    {
    return function( type )/*Boolean*/
        {
        if( (typeof type == "string") || (type instanceof String) )
            {
            type = buRRRn.Reflection.getConstructorByName( type );
            }
        
        if( o === undefined )
            {
            if( type === undefined )
                {
                return true;
                }
            return false;
            }
        
        if( o === null )
            {
            if( type === null )
                {
                return true;
                }
            return false;
            }
        
        if( o.constructor )
            {
            return o.constructor == type;
            }
        
        if( o instanceof type )
            {
            return true;
            }
        return false;
        }
    }


buRRRn.core2.after(); //post-autoexecute

